package main

import "fmt"

// make\new操作
// make只能用于构建map\slice\channel的内存分配,返回一个有初始值的T类型,而不是*T.
//   本质是:make初始化了内部的数据结构,填充适当的值,初始化后返回的是非零值
// new用于构建各种基本数据类型的内存分配,本质是:new(T)分配了零值填充的T类型的内存空间,并返回其地址,即一个*T类型的值.即用go的术语表达为返回一个指针,指向重新分配的类型T的零值
//    并且返回的是指针
//结构体占用一块连续的内存空间
type x struct {
	a int8
	b int8
	c string
}

//结构体指针和初始化
//结构体是值类型
type person struct {
	name, gender string
}

func f(x *person) {
	x.gender = "男"    // 根据内存地址找到那个原变量。修改的就是原来的变量
	(*x).gender = "男" //语法糖。与上面的语句等价
}

type student struct {
	name string
	age  int
}

func main() {
	//结构体占用一块连续的内存空间证明
	mm := x{
		a: int8(10),
		b: int8(11),
		c: "哈哈",
	}
	fmt.Println(&(mm.a), &(mm.b), &(mm.c)) //0xc000114060 0xc000114061 0xc000114068 逢八进一
	//结构体实例化的几种方法
	var p person
	p.name = "俩人"
	p.gender = "女"
	f(&p)
	fmt.Println(p.gender)
	//结构体指针1 并初始化
	var p2 = new(person) //p2的类型是结构体类型的指针 *person
	p2.name = "理想"
	fmt.Printf("%T\n", p2)
	fmt.Printf("%p\n", p2)
	//结构体指针2 并初始化
	// 2.1key-value初始化
	var p3 = person{
		name:   "John",
		gender: "Male",
	}
	fmt.Printf("%#v\n", p3)
	//2.2使用值列表的形式初始化，值的顺序要和结构体定义时的字段顺序一致
	p4 := person{
		"小王子",
		"male",
	}
	fmt.Printf("%#v\n", p4)

	m := make(map[string]*student)
	stus := []student{
		{name: "小王子", age: 18},
		{name: "娜扎", age: 23},
		{name: "大王八", age: 9000},
	}

	for i, stu := range stus {
		m[stu.name] = &stus[i]
	}
	for k, v := range m {
		fmt.Println(k, "=>", v.name)
	}
}
